﻿package clock
{
	import util. *;
	import mvc. *;
	/** * Represents the data of a clock (i.e., the Model of the MVC triad). */
	class ClockModel extends Observable
	{
		// The current hour.
		private var hour : Number;
		// The current minute. private var minute:Number;
		// The current second.
		private var second : Number;
		// The interval identifier for the interval that calls "tick()" once per second.
		private var tickInterval : Number;
		// Indicates whether the clock is running or not.
		private var isRunning : Boolean;
		/** * Constructor. */
		public function ClockModel ()
		{
			// By default, set the clock time to the current system time.
			var now : Date = new Date ();
			setTime (now.getHours () , now.getMinutes () , now.getSeconds ());
		}
		/** * Starts the clock ticking. */
		public function start () : Void
		{
			if ( ! isRunning)
			{
				isRunning = true;
				tickInterval = setInterval (this, "tick", 1000);
				var infoObj : ClockUpdate = new ClockUpdate (hour, minute, second, isRunning);
				setChanged ();
				notifyObservers (infoObj);
			}
		}
		/** * Stops the clock ticking. */
		public function stop () : Void
		{
			if (isRunning)
			{
				isRunning = false;
				clearInterval (tickInterval);
				var infoObj : ClockUpdate = new ClockUpdate (hour, minute, second, isRunning);
				setChanged ();
				notifyObservers (infoObj);
			}
		}
		/** * Sets the current time (i.e., the hour, minute, and second variables. * Notifies observers of any change in time. * * @param h The new hour. * @param m The new minute. * @param s The new second. */
		public function setTime (h : Number, m : Number, s : Number) : Void
		{
			if (h != null && h != hour && isValidHour (h))
			{
				hour = h;
				setChanged ();
			}
			if (m != null && m != minute && isValidMinute (m))
			{
				minute = m;
				setChanged ();
			}
			if (s != null && s != second && isValidSecond (s))
			{
				second = s;
				setChanged ();
			}
			// If the model has changed, notify Views.
			if (hasChanged ())
			{
				var infoObj : ClockUpdate = new ClockUpdate (hour, minute, second, isRunning);
				// Push the changed data to the Views.
				notifyObservers (infoObj);
			}
		}
		/** * Checks to see if a number is a valid hour (i.e., is * an integer in the range 0 to 23.) * * @param h The hour to check. */
		private function isValidHour (h : Number) : Boolean
		{
			return (Math.floor (h) == h && h >= 0 && h <= 23);
		}
		/** * Checks to see if a number is a valid minute (i.e., is * an integer in the range 0 to 59.) * * @param m The minute to check. */
		private function isValidMinute (m : Number) : Boolean
		{
			return (Math.floor (m) == m && m >= 0 && m <= 59);
		}
		/** * Checks to see if a number is a valid second (i.e., is * an integer in the range 0 to 59.) * * @param s The second to check. */
		private function isValidSecond (s : Number) : Boolean
		{
			return (Math.floor (s) == s && s >= 0 && s <= 59);
		}
		/** * Makes time pass by adding a second to the current time. */
		private function tick () : Void
		{
			// Get the current time.
			var h : Number = hour;
			var m : Number = minute;
			var s : Number = second;
			// Increment the current second, adjusting
			// the minute and hour if necessary.
			s += 1;
			if (s > 59)
			{
				s = 0;
				m += 1;
				if (m > 59)
				{
					m = 0;
					h += 1;
					if (h > 23)
					{
						h = 0;
					}
				}
			} // Set the new time. setTime(h, m, s);
		}
	}
}
